home *** CD-ROM | disk | FTP | other *** search
/ Mission 3 / Mission 3.zip / Mission 3.iso / spiele / gemamigo / src / gamewin.cc < prev    next >
C/C++ Source or Header  |  1998-10-29  |  11KB  |  518 lines

  1. #include "amigo.h"
  2. #include "gemui.h"
  3. #include "gamewin.h"
  4. #undef BLACK
  5. #undef WHITE
  6. #include <gemamigo.h>
  7.  
  8. #include <grect.h>
  9. #include <geme.h>
  10. #include <gemr.h>
  11. #include <minmax.h>
  12.  
  13. #define FIS_HOLLOW 0
  14. #define FIS_SOLID 1
  15. #define FIS_PATTERN 2
  16.  
  17.  
  18. extern short    showTrees,showMoveReason,groupInfo;
  19. extern char    *playReason;
  20.  
  21. GameWindow::GameWindow(GEMactivity& act, GEMrsc& rsc) :
  22.     GEMformwindow(act,rsc,GAMEWIN,CLOSER|MOVER|NAME|INFO|SIZER),
  23.     VDI(),
  24.     GEMuserobject(*this,GRID),
  25.     screen(*this),
  26.     colour_choice(rsc,COLOUR_MENU),
  27.     handicap_choice(rsc,HANDICAP_MENU),
  28.     viewwin((({Open();/* Open me first! */}),act),rsc,this),
  29.     game_not_in_progress(rsc.String(NO_GAME)),
  30.     game_over(rsc.String(GAMEOVER)),
  31.     i_am_thinking(rsc.String(THINKING)),
  32.     cpu_passed(rsc.String(CPUPASSED)),
  33.     click_on_dead_groups(rsc.String(COUNTUP)),
  34.     about(rsc,ABOUT)
  35. {
  36.     for (int im=0; im<NUMSTONESIZES; im++) {
  37.         char black_stone_file[]="BLACKST?.IMG";
  38.         char white_stone_file[]="WHITEST?.IMG";
  39.         char  stone_mask_file[]="STN_MAS?.IMG";
  40.         //                       01234567
  41.  
  42.         black_stone_file[7]=im+'0';
  43.         white_stone_file[7]=im+'0';
  44.         stone_mask_file[7]=im+'0';
  45.  
  46.         black_stone[im]=new IMG(black_stone_file);
  47.         white_stone[im]=new IMG(white_stone_file);
  48.         stone_mask[im]=new IMG(stone_mask_file);
  49.  
  50.         //black_stone[im]->TranslateTo(FALSE);
  51.         //white_stone[im]->TranslateTo(FALSE);
  52.         //stone_mask[im]->TranslateTo(FALSE);
  53.  
  54.         //black_stone[im]->ClearCache();
  55.         //white_stone[im]->ClearCache();
  56.         //stone_mask[im]->ClearCache();
  57.     }
  58.  
  59.     SetName(rsc.String(GAMEWIN_TITLE));
  60.     // Don't need to modify them - keep them in dev form.
  61.  
  62.     ingame = counting = 0;
  63.     new_handicap = current_handicap = 0;
  64.     humanColor = WHITE;
  65.     new_color = amigoColor = BLACK;
  66.     amigo_last_x = amigo_last_y = human_last_x = human_last_y = -1;
  67.  
  68.     ShowAndHide();
  69.     ClearBoard();
  70. }
  71.  
  72. void GameWindow::ShowAndHide()
  73. {
  74.     bool redraw=FALSE;
  75.  
  76.     if (Object(NEW_GAME).HideTree(ingame||counting)!=(ingame||counting)) redraw=TRUE;
  77.     if (Object(PASS).HideTree(!ingame)!=!ingame) redraw=TRUE;
  78.     if (Object(COUNTING_DONE).HideTree(!counting)!=!counting) redraw=TRUE;
  79.     if (Object(RESIGN).HideTree(!ingame)!=!ingame) redraw=TRUE;
  80.  
  81.     if (redraw) {
  82.         RedrawObjectFromRoot(VARIABLE_BUTTONS);
  83.         //RedrawObject(CONTROL_PANEL,0,0,Object(CONTROL_PANEL).Width(),Object(VARIABLE_BUTTONS).Height());
  84.     }
  85. }
  86.  
  87. GEMfeedback GameWindow::DoItem(int item, const GEMevent& e)
  88. {
  89.     switch (item) {
  90.      case GRID:
  91.         InputStone(e);
  92.     break; case NEW_GAME:
  93.         NewGame();
  94.     break; case PASS:
  95.         Pass();
  96.     break; case COUNTING_DONE:
  97.         Pass(); // (in Xamigo, pass is used for both)
  98.     break; case RESIGN:
  99.         Resign();
  100.     break; case COLOUR:
  101.         ChooseColour();
  102.     break; case HANDICAP:
  103.         ChooseHandicap();
  104.     break; case SHOW_REASON:
  105.         ; // It's just a flag
  106.     break; case DO_VIEW:
  107.         viewwin.Open();
  108.     break; case DO_ABOUT:
  109.         about.Do();
  110.     }
  111.  
  112.     return ContinueInteraction;
  113. }
  114.  
  115. static bool XThroughRect(int x, GRect& r)
  116. {
  117.     return x>=r.g_x && x<r.g_x+r.g_w;
  118. }
  119.  
  120. static bool YThroughRect(int y, GRect& r)
  121. {
  122.     return y>=r.g_y && y<r.g_y+r.g_h;
  123. }
  124.  
  125. static bool InRect(int x, int y, GRect& r)
  126. {
  127.     return XThroughRect(x,r)
  128.         && YThroughRect(y,r);
  129. }
  130.  
  131. void GameWindow::Draw(const PARMBLK* p)
  132. {
  133.     // Clip
  134.     GRect drawclip(p->pb_xc,p->pb_yc,p->pb_wc,p->pb_hc);
  135.     GRect objclip(p->pb_x,p->pb_y,GEMuserobject::Width(),GEMuserobject::Height());
  136.     drawclip.Clip(objclip);
  137.     clip(drawclip.g_x,drawclip.g_y,drawclip.g_x+drawclip.g_w-1,drawclip.g_y+drawclip.g_h-1);
  138.  
  139.     int size=viewwin.StoneSize();
  140.  
  141.     // Pixel units
  142.     int x=p->pb_x;
  143.     int y=p->pb_y;
  144.     int xspace=(GEMuserobject::Width()-1)/(NUMLINES+1);
  145.     int yspace=(GEMuserobject::Height()-1)/(NUMLINES+1);
  146.     int mx=x+xspace*(NUMLINES+1);
  147.     int my=y+yspace*(NUMLINES+1);
  148.     int spotradius=max(min(xspace,yspace)/5,1);
  149.     int highlightradius=min(xspace/5,min(yspace/5,stone_mask[size]->Width()/2-1));
  150.  
  151.     // Position units (0..NUMLINES-1)
  152.     GRect posclip;
  153.     posclip.g_x=max(0,(drawclip.g_x-x-xspace)/xspace);
  154.     posclip.g_y=max(0,(drawclip.g_y-y-xspace)/yspace);
  155.     posclip.g_w=min(NUMLINES-posclip.g_x,(drawclip.g_w+xspace*2-1)/xspace);
  156.     posclip.g_h=min(NUMLINES-posclip.g_y,(drawclip.g_h+yspace*2-1)/yspace);
  157.  
  158.     // Box
  159.     int pat=viewwin.BoardPattern();
  160.     if (pat>0 && pat<7) {
  161.         sf_color(viewwin.BoardColour());
  162.         sf_interior(FIS_PATTERN);
  163.         sf_style(pat);
  164.     } else {
  165.         sf_color(pat ? viewwin.BoardColour() : 0);
  166.         sf_interior(FIS_SOLID);
  167.     }
  168.     sf_perimeter(1);
  169.     bar(x,y,mx,my);
  170.  
  171.     // Lines
  172.     sl_color(viewwin.LineColour());
  173.     sl_width(1);
  174.  
  175.     // Horizontal lines
  176.     for (int j=0; j<NUMLINES; j++) {
  177.         if (YThroughRect(j,posclip)) {
  178.             line(x+xspace,y+yspace+j*yspace,mx-xspace,y+yspace+j*yspace);
  179.         }
  180.     }
  181.  
  182.     // Vertical lines
  183.     for (int i=0; i<NUMLINES; i++) {
  184.         if (XThroughRect(i,posclip)) {
  185.             line(x+xspace+i*xspace,y+yspace,x+xspace+i*xspace,my-yspace);
  186.         }
  187.     }
  188.  
  189.     // Spots
  190.     const int NUMSPOTS=8;
  191.     const int A=3;
  192.     const int B=NUMLINES/2;
  193.     const int C=NUMLINES-1-3;
  194.     static int spotx[NUMSPOTS]={A,B,C,A,C,A,B,C};
  195.     static int spoty[NUMSPOTS]={A,A,A,B,B,C,C,C};
  196.  
  197.     sf_interior(FIS_SOLID);
  198.     sf_color(viewwin.LineColour());
  199.     for (int s=0; s<NUMSPOTS; s++) {
  200.         if (InRect(spotx[s],spoty[s],posclip))
  201.             circle(x+xspace+spotx[s]*xspace,y+yspace+spoty[s]*yspace,spotradius);
  202.     }
  203.  
  204.     // Stones
  205.     for (j=posclip.g_y; j<posclip.g_y+posclip.g_h; j++) {
  206.         for (i=posclip.g_x; i<posclip.g_x+posclip.g_w; i++) {
  207.             IMG* img=0;
  208.             if (grid[i][j]==BLACK) img=black_stone[size];
  209.             else if (grid[i][j]==WHITE) img=white_stone[size];
  210.             if (img) {
  211.                 int tox=x+xspace+xspace*i-img->Width()/2;
  212.                 int toy=y+yspace+yspace*j-img->Height()/2;
  213.  
  214.                 // Monochrome
  215.                 int b_w[2]={1,0}; // BLACK, WHITE [gemfast #undef'd here though]
  216.                 int w_b[2]={0,1};
  217.                 screen.MonoBlit(MD_TRANS,*stone_mask[size],tox,toy,w_b);
  218.                 screen.MonoBlit(MD_TRANS,*img,tox,toy,b_w);
  219.  
  220.                 // Colour
  221.                 //screen.Blit(DST&!SRC,*stone_mask[size],tox,toy);
  222.                 //screen.Blit(DST|SRC,*img,tox,toy);
  223.             }
  224.         }
  225.     }
  226.  
  227.     // Highlights
  228.     int col=viewwin.HighlightColour();
  229.  
  230.     if (col==0 && amigoColor==WHITE || col==1 && amigoColor==BLACK)
  231.         col=1-col;
  232.  
  233.     sf_color(col);
  234.  
  235.     if (InRect(amigo_last_x,amigo_last_y,posclip)) {
  236.         circle(
  237.             x+xspace+amigo_last_x*xspace,
  238.             y+yspace+amigo_last_y*yspace,
  239.             highlightradius
  240.         );
  241.     }
  242.  
  243.     // Clip off
  244.     clip_off();
  245. }
  246.  
  247. void GameWindow::RedrawPosition(int x, int y)
  248. {
  249.     // From Draw
  250.     int xspace=(GEMuserobject::Width()-1)/(NUMLINES+1);
  251.     int yspace=(GEMuserobject::Height()-1)/(NUMLINES+1);
  252.     // From Draw
  253.     int size=viewwin.StoneSize();
  254.     int tox=xspace+xspace*x-stone_mask[size]->Width()/2;
  255.     int toy=yspace+yspace*y-stone_mask[size]->Height()/2;
  256.  
  257.     RedrawObject(GRID,tox,toy,stone_mask[size]->Width(),stone_mask[size]->Height());
  258. }
  259.  
  260.  
  261. void GameWindow::NewGame()
  262. {
  263.     ingame = 0;
  264.     current_handicap = new_handicap;
  265.     human_passed = amigo_passed = FALSE;
  266.  
  267.     amigo_last_x = amigo_last_y = human_last_x = human_last_y = -1;
  268.     amigoColor = new_color;
  269.     humanColor = (amigoColor==BLACK?WHITE:BLACK);
  270.  
  271.     ClearBoard();
  272.     goRestart(current_handicap);
  273.  
  274.     Message("");
  275.  
  276.     ingame = 1;
  277.  
  278.     if ((amigoColor == BLACK && current_handicap == 0) ||
  279.                 (amigoColor == WHITE && current_handicap > 0))
  280.         AmigoMove();
  281.  
  282.     ShowAndHide();
  283. }
  284.  
  285. void GameWindow::Pass()
  286. {
  287.     if (!ingame && !counting)
  288.     {
  289.         Message(game_not_in_progress);
  290.         return;
  291.     }
  292.  
  293.     if (!ingame)
  294.     {
  295.         if (counting)
  296.         {
  297.             CountUp();
  298.             counting=0;
  299.             ShowAndHide();
  300.         }
  301.         Message("");
  302.         return;
  303.     }
  304.  
  305.     human_passed = TRUE;
  306.     CheckBothPassed();
  307.     if (ingame)
  308.         AmigoMove();
  309. }
  310.  
  311. void GameWindow::Resign()
  312. {
  313.     counting = 0;
  314.     ingame = 0;
  315.     Message(game_over);
  316.     ShowAndHide();
  317. }
  318.  
  319. void GameWindow::ChooseColour()
  320. {
  321.     colour_choice[CHOOSE_BLACK].Checked(new_color==WHITE);// ie. human is black
  322.     colour_choice[CHOOSE_WHITE].Checked(new_color==BLACK);// ie. human is white
  323.  
  324.     GEMobject colour(*this,COLOUR);
  325.  
  326.     int x,y;
  327.     colour.GetAbsoluteXY(x,y);
  328.  
  329.     int item=colour_choice.Do(x,y);
  330.  
  331.     switch (item) {
  332.      case CHOOSE_BLACK:
  333.         new_color=WHITE; // ie. human is white
  334.     break; case CHOOSE_WHITE:
  335.         new_color=BLACK; // ie. human is black
  336.     break; default:
  337.         return;
  338.     }
  339.  
  340.     colour.SetText(colour_choice[item].Text()+2);// 2 = skip checkmark and space
  341. }
  342.  
  343. void GameWindow::ChooseHandicap()
  344. {
  345.     for (int i=NO_HANDICAP; i<=MAX_HANDICAP; i++) {
  346.         handicap_choice[i].Checked(new_handicap==i-NO_HANDICAP);
  347.     }
  348.  
  349.     GEMobject handicap(*this,HANDICAP);
  350.  
  351.     int x,y;
  352.     handicap.GetAbsoluteXY(x,y);
  353.  
  354.     int item=handicap_choice.Do(x,y);
  355.  
  356.     if (item<NO_HANDICAP) return;
  357.  
  358.     new_handicap = item-NO_HANDICAP;
  359.  
  360.     handicap.Text()[0]='0'+new_handicap;
  361. }
  362.  
  363. /*----------------------------------------------------------------
  364. -- AmigoMove()
  365. --    Generate a move for the computer player.  Update
  366. --    message window, mark stone placed.  If we passed, check
  367. --    to see if game is over.
  368. ----------------------------------------------------------------*/
  369. void GameWindow::AmigoMove()
  370. {
  371.     short    x,y;
  372.  
  373.     Message(i_am_thinking);
  374.     if (genMove(amigoColor,&x,&y))
  375.     {
  376.         GoPlaceStone(amigoColor,x,y);
  377.         int ox=amigo_last_x;
  378.         int oy=amigo_last_y;
  379.         amigo_last_x = x;
  380.         amigo_last_y = y;
  381.         RedrawPosition(ox, oy);
  382.         RedrawPosition(amigo_last_x, amigo_last_y);
  383.         if (Object(SHOW_REASON).Selected()) Message(playReason);
  384.         else Message("");
  385.         amigo_passed = FALSE;
  386.     }
  387.     else
  388.     {
  389.         Message(cpu_passed);
  390.         amigo_passed = TRUE;
  391.         CheckBothPassed();
  392.     }
  393. }
  394.  
  395. /*----------------------------------------------------------------
  396. -- CheckBothPassed()                        --
  397. --    Check to see whether the last two moves were both PASS.    --
  398. --    If so, go into `remove dead stone' mode.        --
  399. ----------------------------------------------------------------*/
  400. void GameWindow::CheckBothPassed()
  401. {
  402.     if (human_passed && amigo_passed)
  403.     {
  404.         Message(click_on_dead_groups);
  405.         ingame = 0;
  406.         counting = 1;
  407.         ShowAndHide();
  408.     }
  409. }
  410.  
  411.  
  412. void GameWindow::InputStone(const GEMevent& event)
  413. {
  414.     int ax,ay;
  415.     GetAbsoluteXY(ax,ay);
  416.     int    x = event.X() - ax;
  417.     int    y = event.Y() - ay;
  418.  
  419.     if (!PixelToPosition(x, y)) return;
  420.  
  421.     if (!ingame && counting)
  422.     {
  423.         DeleteGroupFromStone(x,y);
  424.         return;
  425.     }
  426.  
  427.     if (!ingame && !counting)
  428.         return;
  429.  
  430.     if (!GoPlaceStone(humanColor,x,y))
  431.         return;
  432.  
  433.     human_last_x = x;
  434.     human_last_y = y;
  435.  
  436.     human_passed = FALSE;
  437.  
  438.     AmigoMove();
  439. }
  440.  
  441. void GameWindow::ClearBoard()
  442. {
  443.     for (int j=0; j<NUMLINES; j++)
  444.         for (int i=0; i<NUMLINES; i++) {
  445.             grid[i][j]=EMPTY;
  446.         }
  447.     RedrawObject(GRID);
  448. }
  449.  
  450. bool GameWindow::PixelToPosition(int& x, int& y)
  451. {
  452.     // Input:  (x,y) click in grid ((0,0) is top-left, in pixels
  453.     // Output: (x,y) grid position
  454.     int xspace=(GEMuserobject::Width()-1)/(NUMLINES+1);
  455.     int yspace=(GEMuserobject::Height()-1)/(NUMLINES+1);
  456.     x=(x-xspace/2)/xspace;
  457.     y=(y-yspace/2)/yspace;
  458.     GRect range(0,0,NUMLINES,NUMLINES);
  459.     return InRect(x,y,range);
  460. }
  461.  
  462. void GameWindow::PlaceStone(bVal c, int x, int y)
  463. {
  464.     grid[x][y]=c;
  465.     RedrawPosition(x,y);
  466. }
  467.  
  468. void GameWindow::RemoveStone(int x, int y)
  469. {
  470.     grid[x][y]=EMPTY;
  471.     RedrawPosition(x,y);
  472. }
  473.  
  474. void GameWindow::PrisonerReport(int black, int white)
  475. {
  476.     sprintf(Object(BLACK_PRISONERS).Text(),"%3d",black);
  477.     sprintf(Object(WHITE_PRISONERS).Text(),"%3d",white);
  478.     RedrawObject(BLACK_PRISONERS);
  479.     RedrawObject(WHITE_PRISONERS);
  480. }
  481.  
  482. void GameWindow::Message(const char* text)
  483. {
  484.     SetInfoText(text);
  485. }
  486.  
  487. void GameWindow::ViewChanged()
  488. {
  489.     RedrawObject(GRID);
  490. }
  491.  
  492. void GameWindow::SetWorkRect(const GRect& r)
  493. {
  494.     GRect before=WorkRect();
  495.  
  496.     GEMformwindow::SetWorkRect(r);
  497.  
  498.     if (before.g_w!=r.g_w || before.g_h!=r.g_h) {
  499.         Object(0).Resize(r.g_w,r.g_h);
  500.  
  501.         // Top-right
  502.         Object(CONTROL_PANEL).
  503.             MoveTo(
  504.                 r.g_w-Object(CONTROL_PANEL).Width(),
  505.                 0
  506.             );
  507.  
  508.         // Left side, up to about/panel
  509.         Object(GRID).
  510.             Resize(
  511.                 Object(CONTROL_PANEL).X(),
  512.                 r.g_h
  513.             );
  514.  
  515.         RedrawOverlapsViaMessage(WorkRect());
  516.     }
  517. }
  518.